package com.hb.config.aop;

import com.hb.util.ContextUtil;
import com.hb.util.ResultUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.context.annotation.Scope;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Slf4j
@Aspect
@Scope("prototype")
@Component
public class AopCompreConfig {

    /**
     * 日志记录切点
     */
    @Pointcut("execution(public * com.hb..controller.*.*(..))")
    public void webLog() {
    }

    /**
     * 前置通知：在连接点之前执行的通知
     */
    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) {
        // 获取调用的方法名
        String methodName = joinPoint.getSignature().getName();
        String className = joinPoint.getSignature().getDeclaringType().getName();
        log.info(className + "." + methodName + "记录方法前日志＞＞＞");
    }

    /**
     * 异常通知: 抛出异常时调用
     *
     * @param joinPoint
     */
    @AfterThrowing(throwing = "ex", pointcut = "webLog()")
    public void doThrows(JoinPoint joinPoint, Exception ex) {
        String methodName = joinPoint.getSignature().getName();
        String className = joinPoint.getSignature().getDeclaringType().getName();
        log.error(className + "." + methodName + "方法抛出异常: " + ex.getMessage());
    }

    /**
     * 后置通知
     *
     * @throws Throwable
     */
    @Order(-1)
    @After("webLog()")
    public void doAfter() {

    }

    /**
     * 后置通知：当方法返回结果的时候执行
     *
     * @param result
     */
    @AfterReturning(returning = "result", pointcut = "webLog()")
    public void doAfterReturning(JoinPoint joinPoint, Object result) {
        log.info("返回结果记录日志");
    }

    /**
     * 环绕通知
     *
     * @throws Throwable
     */
    @Order(-1)
    @Around("webLog()")
    public Object doAround(ProceedingJoinPoint pjp) {
        Long userId = ContextUtil.getUserId();
        log.info("环绕通知: {}", userId);
        try {
            return pjp.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return ResultUtil.msg(0);
    }
}
